package com.example.opengl.camera

import android.app.Activity
import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.view.Surface
import android.view.SurfaceHolder
import okhttp3.internal.wait
import kotlin.math.abs

/**
 * @author: Mr.You
 * @create: 2023-07-19 14:34
 * @description: 摄像头帮助类
 **/
class CameraHelper private constructor() : Camera.PreviewCallback, SurfaceHolder.Callback {
    //摄像头id
    private var mCameraId: Int = 0
    private var mWidth: Int = 0
    private var mHeight: Int = 0
    private var cameraBuffer: ByteArray? = null
    private var cameraBuffer_: ByteArray? = null
    private var mActivity: Activity? = null
    private var mSurfaceHolder: SurfaceHolder? = null
    private var mCamera: Camera? = null
    private var mPreviewCallback: Camera.PreviewCallback? = null
    private var mOnChangSizeChangedListener: OnChangeSizeListener? = null
    private var mRotation = 0
    private var mSurfaceTexture: SurfaceTexture? = null

    constructor(activity: Activity, cameraId: Int, width: Int, height: Int) : this() {
        this.mActivity = activity
        this.mCameraId = cameraId
        this.mWidth = width
        this.mHeight = height
    }

    fun setPreviewDisPlay(surfaceHolder: SurfaceHolder) {
        mSurfaceHolder = surfaceHolder
        mSurfaceHolder!!.addCallback(this)
    }

    fun switchCamera() {
        if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT
        } else {
            mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK
        }
        stopPreview()
        startPreview(mSurfaceTexture)
    }

     fun startPreview(mSurfaceTexture: SurfaceTexture?) {
        this.mSurfaceTexture = mSurfaceTexture
        try {
            //获取camera对象
            mCamera = Camera.open(mCameraId)
            //获取camera属性信息
            val parameters = mCamera?.parameters
            //设置预览数据为nv21
            parameters?.previewFormat = ImageFormat.NV21
            //设置摄像头宽和高
            setPreviewSize(parameters)
            setPreviewOrientation(parameters)
            mCamera?.parameters = parameters
            cameraBuffer = ByteArray(mWidth * mHeight * 3 / 2)
            cameraBuffer_ = ByteArray(mWidth * mHeight * 3 / 2)
            mCamera?.addCallbackBuffer(cameraBuffer)
            mCamera?.setPreviewCallbackWithBuffer(this)
            mCamera?.setPreviewTexture(mSurfaceTexture)
            mCamera?.startPreview()

        } catch (e: Exception) {

        }
    }

    private fun setPreviewOrientation(parameters: Camera.Parameters?) {
        val cameraInfo = Camera.CameraInfo()
        Camera.getCameraInfo(mCameraId,cameraInfo)
        mRotation = mActivity!!.windowManager.defaultDisplay.rotation
        var degrees = 0
        when(mRotation){
            Surface.ROTATION_0 ->{
                degrees = 0
                mOnChangSizeChangedListener?.onChanged(mHeight,mWidth)
            }
            Surface.ROTATION_90 ->{
                degrees = 90
                mOnChangSizeChangedListener?.onChanged(mWidth,mHeight)
            }
            Surface.ROTATION_180 ->{
                degrees = 180
                mOnChangSizeChangedListener?.onChanged(mHeight,mWidth)
            }
            Surface.ROTATION_270 ->{
                degrees = 270
                mOnChangSizeChangedListener?.onChanged(mWidth,mHeight)
            }
        }
        var result = 0
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
            result = (cameraInfo.orientation + degrees) % 360;
            result = (360 - result) % 360; // compensate the mirror
        } else {
            result = (cameraInfo.orientation - degrees + 360) % 360;
        }
        mCamera?.setDisplayOrientation(result)

    }

    //设置合适的分辨率
    private fun setPreviewSize(parameters: Camera.Parameters?) {
        val supportedPreviewSizes = parameters?.supportedPreviewSizes
        var size = supportedPreviewSizes?.get(0)
        var m = abs((size?.width ?: 0) * (size?.height ?: 0) - mWidth * mHeight)
        supportedPreviewSizes?.removeAt(0)
        val iterator = supportedPreviewSizes?.iterator()
        while (iterator?.hasNext() == true) {
            val next = iterator.next()
            val n = abs((next?.width ?: 0) * (next?.height ?: 0) - mWidth * mHeight)
            if (n < m) {
                m = n
                size = next
            }
        }
        mWidth = size?.width ?: 0
        mHeight = size?.height ?: 0
        parameters?.setPreviewSize(mWidth,mHeight)

    }

    //停止拍摄，并释放资源
    private fun stopPreview() {
        mCamera?.run {
            setPreviewCallback(null)
            stopPreview()
            release()
        }
        mCamera = null
    }

    override fun onPreviewFrame(data: ByteArray?, camera: Camera?) {
        when (mRotation) {
            Surface.ROTATION_0 -> {
                if (data != null) {
                    rotation90(data)
                }
            }

            Surface.ROTATION_90 -> {

            }

            Surface.ROTATION_270 -> {

            }
        }
        mPreviewCallback?.onPreviewFrame(cameraBuffer_, camera)
        camera?.addCallbackBuffer(cameraBuffer)

    }

    private fun rotation90(data: ByteArray) {
        var index = 0
        val ySize = mWidth * mHeight
        // u和v
        val uvHeight = mHeight / 2
        // 后置摄像头顺时针旋转90度
        if (mCameraId === Camera.CameraInfo.CAMERA_FACING_BACK) {
            //将y的数据旋转之后 放入新的byte数组
            for (i in 0 until mWidth) {
                for (j in mHeight - 1 downTo 0) {
                    cameraBuffer_!![index++] = data[mWidth * j + i]
                }
            }

            // 每次处理两个数据
            var i = 0
            while (i < mWidth) {
                for (j in uvHeight - 1 downTo 0) {
                    // v
                    cameraBuffer_!![index++] = data[ySize + mWidth * j + i]
                    // u
                    cameraBuffer_!![index++] = data[ySize + mWidth * j + i + 1]
                }
                i += 2
            }
        } else {
            // 逆时针旋转90度
            for (i in 0 until mWidth) {
                for (j in 0 until mHeight) {
                    cameraBuffer_!![index++] = data[mWidth * j + mWidth - 1 - i]
                }
            }
            //  u v
            var i = 0
            while (i < mWidth) {
                for (j in 0 until uvHeight) {
                    cameraBuffer_!![index++] = data[ySize + mWidth * j + mWidth - 1 - i - 1]
                    cameraBuffer_!![index++] = data[ySize + mWidth * j + mWidth - 1 - i]
                }
                i += 2
            }
        }
    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        TODO("Not yet implemented")
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        stopPreview()
        startPreview(mSurfaceTexture)
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        stopPreview()
    }

    fun getCamera(): Camera? {
      return  mCamera
    }

    interface OnChangeSizeListener {
        fun onChanged(width: Int, height: Int)
    }
}